package wmsignerjx;

public final class Buffer
{
    private static final int INT_BYTES = 4;
    
    public static final void BlockCopy(int[] src, int srcOffset, int[] dst, int dstOffset, int count)
    {
        byte[] bytes = GetBytes(src);
        
        BlockCopy(bytes, srcOffset, dst, dstOffset, count);
    }
    
    public static final void BlockCopy(byte[] src, int srcOffset, int[] dst, int dstOffset, int count)
    {
        if (0 == count)
            return;

        int offset = dstOffset % INT_BYTES;

        int pos = 0;

        if (offset == 0)
        {
            if (srcOffset + count > pos + srcOffset)
                dst[(pos + dstOffset) / INT_BYTES] = (src[pos + srcOffset] & 0x000000FF);

            if (srcOffset + count > pos + srcOffset + 1)
                dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 1] << 8) & 0x0000FFFF);

            if (srcOffset + count > pos + srcOffset + 2)
                dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 2] << 16) & 0x00FFFFFF);

            if (srcOffset + count > pos + srcOffset + 3)
                dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset + 3] << 24);
        }

        if (offset == 1)
        {
            dst[(pos + dstOffset) / INT_BYTES] &= 0x000000FF;

            if (srcOffset + count > pos + srcOffset)
                dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset] << 8) & 0x0000FFFF);

            if (srcOffset + count > pos + srcOffset + 1)
                dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 1] << 16) & 0x00FFFFFF);

            if (srcOffset + count > pos + srcOffset + 2)
                dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset + 2] << 24);
        }

        if (offset == 2)
        {
            dst[(pos + dstOffset) / INT_BYTES] &= 0x0000FFFF;

            if (srcOffset + count > pos + srcOffset)
                dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset] << 16) & 0x00FFFFFF);

            if (srcOffset + count > pos + srcOffset + 1)
                dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset + 1] << 24);
        }

        if (offset == 3)
        {
            dst[(pos + dstOffset) / INT_BYTES] &= 0x00FFFFFF;

            if (srcOffset + count > pos + srcOffset)
                dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset] << 24);
        }

        pos += 4;

        for (; pos <= count - INT_BYTES; pos += INT_BYTES)
        {
            dst[(pos + dstOffset) / INT_BYTES] = (src[pos + srcOffset - offset] & 0x000000FF);
            dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 1 - offset] << 8) & 0x0000FFFF);
            dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 2 - offset] << 16) & 0x00FFFFFF);
            dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset + 3 - offset] << 24);
        }

        if (srcOffset + count > pos + srcOffset - offset)
            dst[(pos + dstOffset) / INT_BYTES] = (src[pos + srcOffset - offset] & 0x000000FF);

        if (srcOffset + count > pos + srcOffset + 1 - offset)
            dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 1 - offset] << 8) & 0x0000FFFF);

        if (srcOffset + count > pos + srcOffset + 2 - offset)
            dst[(pos + dstOffset) / INT_BYTES] |= ((src[pos + srcOffset + 2 - offset] << 16) & 0x00FFFFFF);

        if (srcOffset + count > pos + srcOffset + 3 - offset)
            dst[(pos + dstOffset) / INT_BYTES] |= (src[pos + srcOffset + 3 - offset] << 24);
    }
    
    public static final byte[] GetBytes(int[] value)
    {
        byte[] result = new byte[value.length * 4];

        for(int pos = 0; pos < value.length; pos++)
        {
            result[pos * 4] = (byte)(value[pos] & 0xFF);
            result[pos * 4 + 1] = (byte)((value[pos] >> 8)  & 0xFF);
            result[pos * 4 + 2] = (byte)((value[pos] >> 16) & 0xFF);
            result[pos * 4 + 3] = (byte)((value[pos] >> 24) & 0xFF);
        }

        return result;
    }
    
    public static final void CopyBytes(long src, byte[] dst)
    {
        byte[] temp = new byte[8];

        temp[0] = (byte)(src & 0xFF);
        temp[1] = (byte)(src >> 8 & 0xFF);
        temp[2] = (byte)(src >> 16 & 0xFF);
        temp[3] = (byte)(src >> 24 & 0xFF);
        temp[4] = (byte)(src >> 32 & 0xFF);
        temp[5] = (byte)(src >> 40 & 0xFF);
        temp[6] = (byte)(src >> 48 & 0xFF);
        temp[7] = (byte)(src >> 56 & 0xFF);

        for(int pos = 0; pos < temp.length; pos++)
            dst[pos] = temp[pos];
    }
}
